home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / arcers / tar316.zip / EXTRACT.C < prev    next >
Text File  |  1994-07-21  |  15KB  |  522 lines

  1. /* extarct.c - extract files from (tape) archive.
  2.  * This is a part of the Tar program (see file tar.c)
  3.  * Author: T.V.Shaporev
  4.  * Creation date: 14 Dec 1990
  5.  */
  6. #include <stdio.h>
  7.  
  8. #include "sysup.h"
  9. #include "nodedef.h"
  10. #include "modern.h"
  11. #ifdef MODERN
  12. #    include <string.h>
  13. #else
  14.     char *strncpy();
  15.     int  strlen();
  16. #endif
  17. #ifndef MSDOS
  18.     int  mknod(), chown(), utime();
  19.     long time();
  20. #endif
  21.  
  22. #include "zippipe.h"
  23. #include "zipdefs.h"
  24. #include "lzwbits.h"
  25. #include "lzwhead.h"
  26. #include "compress.h"
  27. #include "define.h"
  28. #include "lzpack.h"
  29.  
  30. static int soctus   __ARGS__(( register char *, register short* ));
  31.        int soctul   __ARGS__(( register char *, register long * ));
  32.        int shexul   __ARGS__(( register char *, register long * ));
  33.  
  34. #define octal(c) (((c)&0370)=='0')
  35.  
  36. static char unknown[] = "Tar: \'%s\' unknown file type \'%c\'\n";
  37. #define _unknown (unknown+9)
  38.  
  39. static int soctus(s, u)
  40. register short *u;
  41. register char *s;
  42. {
  43.    register i;
  44.    while (*s == ' ') ++s;
  45.    for (*u=0, i=0; octal(*s) && i<7; i++, s++) *u = (*u<<3)|(*s&7);
  46.    return *s!=' ' && *s!='\0';
  47. }
  48.  
  49. int soctul(s, u)
  50. register long *u;
  51. register char *s;
  52. {
  53.    register i;
  54.    while (*s == ' ') ++s;
  55.    for (*u=0, i=0; octal(*s) && i<11; i++, s++) *u = (*u<<3)|(*s&7);
  56.    return *s!=' ' && *s!='\0';
  57. }
  58.  
  59. int shexul(s, u)
  60. register long *u;
  61. register char *s;
  62. {
  63.    register i, k;
  64.    while (*s == ' ') ++s;
  65.    for (*u=0, i=0; i<8; i++, s++) {
  66.       k = *s;
  67.       if      (k >= '0' && k <= '9') k -= '0';
  68.       else if (k >= 'A' && k <= 'F') k -= 'A'-10;
  69.       else if (k >= 'a' && k <= 'f') k -= 'a'-10;
  70.       else break;
  71.       *u = (*u << 4) | k;
  72.    }
  73.    return *s!=' ' && *s!='\0';
  74. }
  75.  
  76. int pktest(p)
  77. unsigned char *p;
  78. {
  79.    register unsigned k;
  80.  
  81.    if (pklock || i_flag || pktype != PKNONE) return ERROR;
  82.    pklock = TRUE;
  83.  
  84.    k = ((unsigned)(p[1]) << 8) | p[0];
  85.    if (k == (unsigned)((LZW_1ST_MAGIC << 8) | LZW_0TH_MAGIC)) {
  86.       pktype = PKpLZW;
  87.    } else if (k == GZIP_MAGIC ||
  88.               k == PKW_01_MAGIC &&
  89.               (((unsigned)(p[3]) << 8) | p[2]) == PKW_23_MAGIC) {
  90.       pktype = PKZIP;
  91.    } else {
  92.       return ERROR;
  93.    }
  94.    if (pkalloc()) {
  95.       (void)fprintf(stderr, "No memory for decompression\n");
  96.       done(ESMALL);
  97.    }
  98.    if (redirect()) done(EINTER);
  99.    return CORRECT;
  100. }
  101.  
  102. int gethead()
  103. {
  104.    short n;
  105.    static short errcount = 0;
  106.    register char *err_text = "Tar: bad directory structure\n";
  107.  
  108.    for (;;) {
  109.       if ((hblock = readtape()) == NULL) return ERROR;
  110.       if ((hblock->m.name[0]) == '\0') {
  111.          return errcount ? (++errcount, ERROR) : FALSE;
  112.       }
  113.       if (soctus(hblock->m.chksum, &n) == CORRECT) {
  114.          if (n == headsum(hblock)) break;
  115.          err_text = "Tar: directory checksum error\n";
  116.       }
  117.       if (pktest((unsigned char*)(hblock->m.name))) goto bad;
  118.    }
  119.    if (soctus(hblock->m.mode,  (short*)&(st.st_mode)) ||
  120.        soctus(hblock->m.uid,   (short*)&(st.st_uid))  ||
  121.        soctus(hblock->m.gid,   (short*)&(st.st_gid))  ||
  122.        soctul(hblock->m.size,  (long *)&(st.st_size)) ||
  123.        soctul(hblock->m.mtime, (long *)&(st.st_mtime))) goto bad;
  124.    if (hblock->m.filetype == TF_CHR || hblock->m.filetype == TF_BLK) {
  125.       if (soctus(hblock->x.devmajor, &dmajor) ||
  126.           soctus(hblock->x.devminor, &dminor)) goto bad;
  127.    }
  128.    if (errcount != 0) {
  129.       (void)fprintf(myout,
  130.                     "Tar: %d blocks skipped to find header\n", errcount);
  131.       errcount = 0;
  132.    }
  133.    if (hblock->m.filetype != TF_OLD && hblock->m.filetype != TF_REG) {
  134.       longcsum = codesize = 0L;
  135.    } else if (hblock->m.srcsum[1]!='x' || hblock->m.srcsum[0]!='0') {
  136.       (void)soctul(hblock->m.srclen, &codesize); /* no sence for    */
  137.       (void)soctul(hblock->m.srcsum, &longcsum); /* non-packed file */
  138.    } else {
  139.       (void)shexul(hblock->m.srclen + 2, &codesize);
  140.       (void)shexul(hblock->m.srcsum + 2, &longcsum);
  141.    }
  142.    return TRUE;
  143. bad:
  144.    if (errcount++ == 0) (void)fprintf(myout, err_text);
  145.    if (!i_flag) done(ERREAD);
  146.    return ERROR;
  147. }
  148.  
  149. static int tstfield __ARGS__(( char *, int ));
  150.  
  151. static int tstfield(s,n) /* is the field a valid octal number? */
  152. char *s; int n;
  153. {
  154.    register j;
  155.  
  156.    for (j=0; j<n && octal(s[j]); j++);
  157.    if (!j || j >= n) return FALSE;
  158.    if (s[j] == ' ') ++j;
  159.    while (j<n && !s[j++]);
  160.    return j>=n;
  161. }
  162.  
  163. #define TstField(x) tstfield(x, sizeof(x))
  164.  
  165. short isextent(allx, allb)
  166. short *allx; long *allb;
  167. {
  168.    short n;
  169.  
  170.    if ((hblock->m.filetype != TF_OLD && hblock->m.filetype != TF_REG) ||
  171.        !TstField(hblock->s.extent) ||
  172.        !TstField(hblock->s.allext) ||
  173.        !TstField(hblock->s.total)) return ERROR;
  174.    (void)soctus(hblock->s.extent, &n);
  175.    (void)soctus(hblock->s.allext, allx);
  176.    (void)soctul(hblock->s.total,  allb);
  177.    return n < 1 || n > *allx || *allb <= st.st_size ? ERROR : n;
  178. }
  179.  
  180. int ismagic()
  181. {
  182.    register i;
  183.    register char *p, *q;
  184.    static char magic_list[][8] = { TMAGIC, GMAGIC };
  185.  
  186.    if (hblock->m.filetype != TF_OLD) {
  187.       for (i=0; i<dimof(magic_list); i++) {
  188.          p = magic_list[i];
  189.          q = hblock->x.magic;
  190.          while (*q && *q == *p) {
  191.             ++q; p++;
  192.          }
  193.          if (*q == '\0' && (*p == '\0' || *p == ' '))
  194.             return magic_list[i][0];
  195.       }
  196.    }
  197.    return 0;
  198. }
  199.  
  200. char prefix()
  201. {
  202.    switch (hblock->m.filetype) {
  203.       case TF_CTG: /* ??? contiguous file */
  204.       case TF_OLD:
  205.       case TF_REG:
  206.       case TF_LNK: return ' ';
  207.       case TF_SYM: return 'l';
  208.       case TF_CHR: return 'c';
  209.       case TF_BLK: return 'b';
  210.       case TF_DIR: return 'd';
  211.       case TF_QUE: return 'p';
  212.       case GF_DMP: return 'D';
  213.       case GF_MUL: return ',';
  214.       case GF_VOL: return 'v';
  215.    }
  216.    return '?';
  217. }
  218.  
  219. int usize() /* is it valid to use file size in header */
  220. {
  221.    switch (hblock->m.filetype) {
  222.       case TF_OLD: case TF_REG: case TF_CTG:
  223.       case GF_DMP: case GF_MUL: case GF_SPR: /* what's it? I wonder */
  224.          return TRUE;
  225.    }
  226.    return FALSE;
  227. }
  228.  
  229. void skipfile()
  230. {
  231.    register long blocks;
  232.  
  233.    for (blocks=(st.st_size+BLKSIZE-1)/BLKSIZE; blocks>0; blocks--) {
  234.       if (readtape() == NULL) {
  235.          (void)fprintf(myout, "Tar: tape read error\n");
  236.          if (i_flag) done(ERREAD);
  237.          return;
  238.       }
  239.    }
  240. }
  241.  
  242. static inlist __ARGS__((int, char**, char*));
  243.  
  244. static int inlist(argc, argv, n)
  245. int argc; register char *argv[], *n;
  246. {
  247.    register i; register j; register k;
  248.    register char *p;
  249.  
  250.    for (i=0; i<argc; i++) {
  251.       if (s_flag) {
  252.          for (p=argv[i], j=0; j<MAXTNAME && p[j]==n[j] && p[j]!=0; j++);
  253.          if (j<MAXTNAME && p[j]==0 && (n[j]==0 || n[j]=='/')) return TRUE;
  254.       } else {
  255.          for (j=0; j<MAXTNAME && n[j];) {
  256.             do ++j; while (n[j]!='/' && n[j]!=0);
  257.             if ((k = mismatch(argv[i], n, j)) == ERROR) break;
  258.             if (!k) return TRUE;
  259.          }
  260.       }
  261.    }
  262.    return FALSE;
  263. }
  264.  
  265. int inargs(argc, argv, n)
  266. int argc; char *argv[], *n;
  267. {
  268.    return inlist(argc, argv, n) && !inlist(xcnt, xarg, n);
  269. }
  270.  
  271. void scantape(argc, argv, handler)
  272. int argc; char *argv[]; void (*handler)__ARGS__((void));
  273. {
  274.    register k;
  275.  
  276.    while ((k=gethead()) != FALSE) {
  277.       pklock = TRUE;
  278.       if (k == ERROR) continue;
  279.       if ((argc < 1 ||  inlist(argc, argv, hblock->m.name)) &&
  280.           (xcnt < 1 || !inlist(xcnt, xarg, hblock->m.name))) {
  281.          (*handler)();
  282.       } else {
  283.          if (usize()) skipfile();
  284.       }
  285.    }
  286.    if (pktype == PKZIP) {
  287.       while ((k=unzread((char*)hblock, BLKSIZE)) == BLKSIZE);
  288.       if (k != ERROR) {
  289.          if (k) (void)fprintf(myout, "Tar: final block misaligned\n");
  290.          k = unzclose();
  291.       }
  292.       if (k) {
  293.          register char *p = NULL;
  294.          if (k == -1) p = "error"; else if (v_flag) p = "warning";
  295.          if (p) (void)fprintf(myout, "Tar: unzip %s: %s\n",
  296.                                      p, ziperrlist[ziperror]);
  297.       }
  298.    }
  299. }
  300.  
  301. extern long thisread;
  302. extern int arcget __ARGS__(( void ));
  303.  
  304. void catalog()
  305. {
  306.    register long thislen;
  307.    register reverse = FALSE, skipped = FALSE;
  308.    register char *p;
  309.    static no_mem = FALSE;
  310.    short nx = 1, allx; long xinfo;
  311.    extern char ofname[];
  312.    register c;
  313.  
  314.    p = hblock->m.name;
  315.    c = hblock->m.filetype;
  316.  
  317.    if (v_flag) prmode(prefix(), (int)(st.st_mode));
  318.    if ((c == TF_OLD || c == TF_REG) && (nx=isextent(&allx, &xinfo)) < 1) {
  319.       if (st.st_size <= codesize) {
  320.          reverse = TRUE;
  321.       } else if (pktype == PKfLZW) {
  322.          register i, j;
  323.  
  324.          i = strlen(hblock->m.name);
  325.          if (hblock->m.name[--i] == 'Z' && hblock->m.name[--i] == '.') {
  326.             p = strncpy(ofname, hblock->m.name, MAXTNAME);
  327.             (void)z_getmem(BITS);
  328.             codesize = 0; thisread = 0;
  329.             if ((j = dbegin(arcget)) == 0) {
  330.                do {
  331.                   if ((j = dpiece(pk_out, pksize)) > 0) codesize += j;
  332.                } while (j == pksize);
  333.                skipped = TRUE;
  334.             } else if (j > 0) {
  335.                bacouple(); /* file is not in compressed format */
  336.             } else if (!no_mem) {
  337.                (void)fprintf(myout, "Tar: not enough memory to uncompress\n");
  338.                no_mem = TRUE;
  339.             }
  340.          }
  341.       }
  342.       thislen = codesize > st.st_size ? codesize : st.st_size;
  343.    } else {
  344.       thislen = st.st_size;
  345.    }
  346.    if (v_flag) {
  347.       (void)fprintf(myout, " %3d/%1d ", st.st_uid, st.st_gid);
  348.       if (c == TF_CHR || c == TF_BLK) {
  349.          (void)fprintf(myout,
  350.             pkfile ? "%10d,%-5d " : "%3d,%-3d ", dmajor, dminor);
  351.       } else {
  352.          (void)fprintf(myout, "%7ld ", reverse ? thislen : st.st_size);
  353.          if (pkfile) {
  354.             if ((c == TF_OLD || c == TF_REG) && st.st_size <= codesize) {
  355.                (void)fprintf(myout,
  356.                   reverse && hblock->m.srcsum[1] != 'x' ?
  357.                      "{%7ld} " : "(%7ld) ",
  358.                   reverse ? st.st_size : codesize);
  359.             } else {
  360.                (void)fprintf(myout, "          ");
  361.             }
  362.          }
  363.       }
  364.    }
  365.    (void)fprintf(myout, "%-.*s", MAXTNAME, p);
  366.  
  367.    switch (c) {
  368.       case TF_LNK:
  369.       case TF_SYM:
  370.          if (v_flag) (void)fprintf(myout, "\n");
  371.          (void)fprintf(myout, " %s to %s\n",
  372.             c == TF_SYM ? "symlink" : "linked",
  373.             hblock->m.linkname);
  374.          break;
  375.       case TF_OLD:
  376.       case TF_REG:
  377.          if (nx >= 1) {
  378.             if (v_flag) (void)fprintf(myout, "\n");
  379.             (void)fprintf(myout, " [extent #%d of %d]", nx, allx);
  380.             if (v_flag) (void)fprintf(myout, " %ld bytes total", xinfo);
  381.          }
  382.       case TF_CHR: case TF_BLK:
  383.       case TF_DIR: case TF_QUE: case TF_CTG:
  384.       case GF_DMP: case GF_VOL:
  385.          (void)fprintf(myout, "\n");
  386.          break;
  387.       case GF_MUL:
  388.          if (v_flag) (void)fprintf(myout, "\n");
  389.          (void)soctul(hblock->x.offset, &xinfo);
  390.          (void)fprintf(myout, "[from %ld to %ld]",
  391.                               xinfo, xinfo+st.st_size-1);
  392.          (void)fprintf(myout, "\n");
  393.          break;
  394.       default:
  395.          if (v_flag) (void)fprintf(myout, "\n");
  396.          (void)fprintf(myout, _unknown, c);
  397.    }
  398.    if (nx < 1 && v_flag && j_flag && /*dummy*/!skipped &&
  399.        hblock->m.comment[0] && !ismagic()) {
  400.       (void)fprintf(myout, "> %s\n", hblock->m.comment);
  401.    }
  402.    if (usize()) {
  403.       if (!skipped) skipfile();
  404.       allbytes += thislen;
  405.    }
  406.    ++allfiles;
  407. }
  408.  
  409. static char *cutname __ARGS__((register char *p));
  410.  
  411. static char *cutname(p)
  412. register char *p;
  413. {
  414.    register j;
  415.  
  416.    if (nonest) {
  417.       j = strlen(p);
  418.       while (j>0 && p[j-1] != '/'
  419. #ifdef MSDOS
  420.              && p[j-1] != ':'
  421. #endif
  422.             ) --j;
  423.       p += j;
  424.    } else {
  425. #ifdef MSDOS
  426.       if (deldrv && p[1] == ':' &&
  427.                    (p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z'))
  428.          p += 2;
  429. #endif
  430.       if (dslash && *p == '/') ++p;
  431.    }
  432.    return p;
  433. }
  434.  
  435. void extract()
  436. {
  437.    register j, k;
  438.    register char *p;
  439.    extern int makedir __ARGS__((char *, int));
  440.    extern int testdir __ARGS__((char *));
  441.  
  442.    p = cutname(hblock->m.name);
  443.    if (u_flag) {
  444.       struct stat s;
  445.  
  446.       if (stat(p, &s)==0 && s.st_mtime >= st.st_mtime) {
  447.          if (usize()) skipfile(); return;
  448.       }
  449.    }
  450.    if (w_flag && !okwork('x', prefix(), &st, p)) {
  451.       if (usize()) skipfile(); return;
  452.    }
  453.    if ((j=strlen(p)-1) >= 0 && p[j] == '/') {/* directory with permissions */
  454.       if (testdir(p) != TRUE) return;
  455.       p[j] = '\0';
  456.    } else if (hblock->m.filetype == TF_DIR || hblock->m.filetype == GF_DMP) {
  457.       k = FALSE;
  458.       if (makedir(p, FALSE) != 0) {
  459.          if (testdir(p) != TRUE || makedir(p, TRUE) != 0) k = TRUE;
  460.       }
  461.       if (usize()) skipfile();
  462.       if (k) return;
  463.    } else if (hblock->m.filetype == TF_LNK) {
  464.       makelink(p, cutname(hblock->m.linkname)); return;
  465.    } else if (hblock->m.filetype == TF_OLD || hblock->m.filetype == TF_REG) {
  466.       if (restore(p) != 0) return;
  467. #ifdef UNIX
  468.    } else if (hblock->m.filetype == TF_CHR || hblock->m.filetype == TF_BLK ||
  469.               hblock->m.filetype == TF_QUE) {
  470.       st.st_mode &= 07777;
  471.       if (hblock->m.filetype != TF_QUE) {
  472.          st.st_mode |= hblock->m.filetype == TF_BLK ? S_IFBLK : S_IFCHR;
  473.          st.st_rdev  = makedev(dmajor, dminor);
  474.       } else {
  475.          st.st_mode |= S_IFIFO;
  476.          st.st_rdev  = 0;
  477.       }
  478.       j = 0;
  479.       k = FALSE;
  480.       do {
  481.          if (mknod(p, st.st_mode, st.st_rdev) == 0) break;
  482.       } while (++j < 2 && (k = testdir(p)) == TRUE);
  483.       if (j > 1) (void)fprintf(myout, "Tar: can\'t create \'%s\'\n", p);
  484.       if (j > 1 || k == ERROR) return;
  485.       if (v_flag) (void)fprintf(myout, "x %s\n", p);
  486. #endif
  487.    } else {
  488.       (void)fprintf(myout, unknown, p, hblock->m.filetype);
  489.       return;
  490.    }
  491. #ifdef UNIX
  492.    if (!o_flag) (void)chown(p, (int)st.st_uid, (int)st.st_gid);
  493.    if (!m_flag) {
  494.       long t[2];
  495.  
  496.       t[0] = time(t);
  497.       t[1] = st.st_mtime;
  498.       (void)utime(p, t);
  499.    }
  500. #endif
  501. }
  502.  
  503. void uplist()
  504. {
  505.    register struct node *this; struct node *prev;
  506.  
  507.    if ((this = finditem(hblock->m.name, &prev, timehead)) == NONE) {
  508.       if ((this = additem(hblock->m.name, prev, &timehead)) == NONE) {
  509.          outmem(myout);
  510.       }
  511.       this->info.time = st.st_mtime;
  512.    } else {
  513.       if (this->info.time < st.st_mtime) this->info.time = st.st_mtime;
  514.    }
  515. }
  516.  
  517. void acctime()
  518. {
  519.    if (u_flag) uplist();
  520.    if (usize()) skipfile();
  521. }
  522.